<?php

/**
 * Albireo Kernel
 *
 * @copyright  Copyright (c) 2010 Albireo Solutions
 * @package    Kernel
 */

namespace KernelModule\ModulesModule;

use Nette\Environment;
use Nette\Forms\Form;

use KernelModule\BasePresenter;

use Albireo\MenuGenerator;
use Albireo\Forms\AlbireoForm;

use Celebrio\Core\ModuleLoader;
use Celebrio\Core\ModuleInstaller;
use Celebrio\Core\ManifestLoader;
use Celebrio\Core\ClassNotFoundException;

use \NotSupportedException;

/**
 * Kernel modules management presenter.
 *
 * @author     Albireo Solutions
 * @package    Kernel
 */
class ModulesManagementPresenter extends BasePresenter {

    /** @persistent */
    public $fullName;
    
    /**
     * Render default action
     */
    public function renderDefault() {
        $this->getTemplate()->title = _("Modules Management");
        $this->showMenu();

        $this->getTemplate()->modules = $this->getModuleList();
    }
    
    /**
     * Renders the list of available implementations (modules) for the given
     * interface (module). Service modules should have only 1, abstract modules
     * more.
     */
    public function actionSelect($fullName) {
        $manifestLoader = new ManifestLoader();
        $manifest = $manifestLoader->getManifest($fullName);
        
        $implementations = $manifestLoader->getImplementationsFor($manifest);

        $implementations = array_filter($implementations, function($manifest) {
            return $manifest->isAvailableToInstall();
        });

        switch (count($implementations)) {
            case 0 : 
                $this->flashMessage(sprintf(_("No implementation of abstract module %s found."), $manifest->getFullNameDots()), "error");
                $this->redirect("default");
                break;
//            case 1 :
//                // install the only implementation immediately
//                $impl = $implementations[0];
//                $implementationFullName = $impl->getFullNameDots();
//                $this->redirect("install", array($implementationFullName));
//                break;
            default :
                // let the user select the implementation
                $this->getTemplate()->implementations = $implementations;
                $this->getTemplate()->title = sprintf(_("Select the implementation for %s module:"),$manifest->getName());
                $this->showMenu();
        }
    }
    
    public function actionInstall($fullName) { }

    public function actionUninstall($fullName) {

        $manifestLoader = new ManifestLoader();
        $manifest = $manifestLoader->getManifest($fullName);
        
        $installer = new ModuleInstaller();
        $installer->uninstall($manifest);
        
        $this->flashMessage(_("The module has been uninstalled succesfuly."));
        $this->redirect("default");

    }
    
    protected function createComponentForm() {
        $form = new AlbireoForm();
        $formFields = $this->getFormFields();
        
        foreach ($formFields as $field) {
            switch ($field["type"]) {
                case "text" :
                    $item = $form->addText($field["name"], $field["label"]);
                    break;
                case "password" :
                    $item = $form->addPassword($field["name"], $field["label"]);
                    break;
                default :
                    throw new NotSupportedException("Unknown settings form field type: " . $field["type"]);
            }
            
            if (isset($field["required"])) {
                $item->addRule(Form::FILLED, $field["required"]);
            }
        }
        
        $form->addSubmit('save', _('Save'));

        $form->onSubmit[] = callback($this, 'formSubmitted');
        
        return $form;
    }
    
    public function formSubmitted($form) {
        $configuration = $form->values;
        
        $manifestLoader = new ManifestLoader();
        $manifest = $manifestLoader->getManifest($this->fullName);
        
        $installer = new ModuleInstaller();
        $installer->install($manifest, $configuration);
        
        
        $this->flashMessage(_("The module has been installed succesfuly."));
        $this->redirect("default");
    }
    
    
    
    
    private function getModuleList() {
        $mfLoader = new ManifestLoader();
        $manifests = $mfLoader->getActivable();
        
        $moduleLoader = new ModuleLoader();
        
        $modules = array();
        foreach ($manifests as $manifest) {
            $moduleFullName = $manifest->getFullNameDots();
            $modules[$moduleFullName] = array(
                    "name" => $manifest->getName(),
                    "description" => $manifest->getDescription(),
                    "dependencies" => $manifest->getDependencies(),
                    "installed" => $manifest->isInstalled(),
                );
        }
        return $modules;
    }
    
    private function getFormFields() {
        
        $manifestLoader = new ManifestLoader();
        $manifest = $manifestLoader->getManifest($this->fullName);
        
        $init = $manifest->getInit();
        if ($init == null) {
            throw new NotSupportedException("Null init. Not supported yet.");
        }
        
        $formFields = $init->formFields();
        return $formFields;
    }

}